﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.XSchEmA.Aspect;
using Pixysoft.Framework.XSchEmA.Hinter;
using Pixysoft.Framework.XSchEmA.Entity;
using Pixysoft.Framework.Verifications;

namespace Pixysoft.Framework.XSchEmA.Modifier
{
    partial class ColumnModifier : IColumnModifier
    {
        /// <summary>
        /// 修改类型 级联所有外键关联都修改
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="datatype">The datatype.</param>
        /// <param name="database">The database.</param>
        /// <param name="table">The table.</param>
        /// <param name="column">The column.</param>
        /// <returns></returns>
        public bool ChangeDataType(DatabaseSchema database, TableSchema table, ColumnSchema column, DataTypeSchema dataType)
        {
            dataType.Inspection();

            column.DataType = dataType;

            List<ColumnSchema> columnList = database.GetStrongForeignColumnChain(column);

            foreach (ColumnSchema fcolumn in columnList)
                fcolumn.DataType = dataType;

            return true;
        }

        /// <summary>
        /// 删除对应的唯一索引、建主键、复原原外键
        /// </summary>
        /// <param name="database"></param>
        /// <param name="pkName"></param>
        /// <param name="table"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public PrimaryKeySchema CreatePrimaryKey(DatabaseSchema database,
            string pkName, TableSchema table, List<ColumnSchema> columns)
        {
            if (columns == null || columns.Count == 0)
                throw new Exception();


            //DELETE CONFLICT UNIQUE

            UniqueSchema unique = database.GetUnique(columns);

            if (unique != null)
                database.Uniques.Remove(unique);


            //CREATE PRIMARY KEY

            PrimaryKeySchema pk = new PrimaryKeySchema(pkName, table, columns);

            pk.Inspection();

            database.PrimaryKeys.Add(pk);

            pk.Refresh();


            //RENAME FOREIGN KEY .

            //2010-08-01 what about index???

            if (unique != null)
                foreach (ForeignKeySchema fk in database.GetBeingForeignKeys(unique.Columns))
                    fk.PkeyConsName = pkName;


            return pk;
        }

        public bool CreatePrimaryKey(DatabaseSchema database, PrimaryKeySchema pk)
        {
            database.PrimaryKeys.Add(pk);

            database.BuildPrimaryKeys();

            return true;
        }

        public bool DeletePrimaryKey(DatabaseSchema database, PrimaryKeySchema pk)
        {
            foreach (ForeignKeySchema fk in database.GetBeingForeignKeys(pk.Columns))
                database.ForeignKeys.Remove(fk);

            database.PrimaryKeys.Remove(pk);

            return true;
        }

        public bool CreateForeignKey(DatabaseSchema database, ForeignKeySchema fk)
        {
            database.ForeignKeys.Add(fk);

            database.BuildForeignKeys();

            return true;
        }

        public bool DeleteForeignKey(DatabaseSchema database, ForeignKeySchema fk)
        {
            database.ForeignKeys.Remove(fk);

            return true;
        }

        public ForeignKeySchema[] DeleteForeignKeys(DatabaseSchema database, string tableName)
        {
            TableSchema table = database.GetTable(tableName);

            if (table == null)
                throw new Exception("missing tablename");

            List<ForeignKeySchema> fks = new List<ForeignKeySchema>();

            foreach (ForeignKeySchema fk in database.GetForeignKeys(table))
            {
                database.ForeignKeys.Remove(fk);
                fks.Add(fk);
            }

            foreach (ForeignKeySchema fk in database.GetBeingForeignKeys(table))
            {
                database.ForeignKeys.Remove(fk);
                fks.Add(fk);
            }

            database.Build();

            return fks.ToArray();
        }



        public UniqueSchema CreateUnique(DatabaseSchema database,
            string constraintName, TableSchema table, List<ColumnSchema> columns)
        {
            if (columns == null || columns.Count == 0)
                throw new Exception();


            UniqueSchema unique = new UniqueSchema(constraintName, table, columns);

            unique.Refresh();

            database.Uniques.Add(unique);

            return unique;
        }

        public bool CreateUnique(DatabaseSchema database, UniqueSchema unique)
        {
            database.Uniques.Add(unique);

            database.BuildUniques();

            return true;
        }

        public bool DeleteUnique(DatabaseSchema database, UniqueSchema unique)
        {

            foreach (ForeignKeySchema fk in database.GetBeingForeignKeys(unique.Columns))
                database.ForeignKeys.Remove(fk);

            if (unique != null)
                database.Uniques.Remove(unique);

            return true;
        }


        public IndexSchema CreateIndex(DatabaseSchema database,
                  string constraintName, TableSchema table, List<ColumnSchema> columns)
        {
            if (columns == null || columns.Count == 0)
                throw new Exception();


            IndexSchema index = new IndexSchema(constraintName, table, columns);

            index.Refresh();

            database.Indexs.Add(index);

            return index;
        }

        public bool CreateIndex(DatabaseSchema database, IndexSchema index)
        {
            database.Indexs.Add(index);

            database.BuildIndexs();

            return true;
        }

        public bool DeleteIndex(DatabaseSchema database, IndexSchema index)
        {

            foreach (ForeignKeySchema fk in database.GetBeingForeignKeys(index.Columns))
                database.ForeignKeys.Remove(fk);

            if (index != null)
                database.Indexs.Remove(index);

            return true;
        }


        public ColumnSchema AddColumn(DatabaseSchema database, TableSchema table, string columnName)
        {
            columnName = columnName.ToUpper().Trim();

            ColumnSchema column = new ColumnSchema(table.TableName, columnName, aspect.GetDefaultDataType());

            column.Inspection();

            table.Columns.Add(column);

            table.BuildColumns();

            return column;
        }

        public bool AddColumn(DatabaseSchema database, TableSchema table, ColumnSchema column)
        {
            column.Inspection();

            table.Columns.Add(column);

            table.BuildColumns();

            return true;
        }

        public bool DeleteColumn(DatabaseSchema database, ColumnSchema column)
        {
            RemoveConstraint(database, column);

            column.Table.Columns.Remove(column);

            return true;
        }

        /// <summary>
        /// 删除相关的外键，查找被清空的外键、主键、唯一，并删除（通过column.count知道哪些被删除、修改）
        /// </summary>
        /// <param name="database"></param>
        /// <param name="column"></param>
        private void RemoveConstraint(DatabaseSchema database, ColumnSchema column)
        {
            foreach (ForeignKeySchema fk in database.GetForeignKeys(column))
            {
                database.ForeignKeys.Remove(fk);
            }

            foreach (ForeignKeySchema fk in database.GetBeingForeignKeys(column))
            {
                database.ForeignKeys.Remove(fk);
            }

            foreach (UniqueSchema unique in database.GetUniques(column))
            {
                database.Uniques.Remove(unique);
            }

            foreach (IndexSchema index in database.GetIndexs(column))
            {
                database.Indexs.Remove(index);
            }

            if (!database.IsPrimaryKey(column))
                return;

            PrimaryKeySchema pk = database.GetPrimaryKey(column.TableName, column.ColumnName);
            if (pk != null)
            {
                database.PrimaryKeys.Remove(pk);
            }
        }
    }
}
